home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Snippets / binhex / binhex.c next >
Encoding:
C/C++ Source or Header  |  1994-03-26  |  27.7 KB  |  1,626 lines  |  [TEXT/KAHL]

  1. #include "rnmac.h"
  2.  
  3. #define CR        ((unsigned char) 0x0D)
  4. #define LF        ((unsigned char) 0x0A)
  5. #define TAB        ((unsigned char) 0x09)
  6. #define SPACE     ((unsigned char) 0x20)
  7. #define RLFLAG    ((unsigned char) 0x90)
  8.  
  9. #define HEXTYPE            'TEXT'
  10. #define HEXCREATOR        '????'
  11.  
  12. #define BUFFSIZE    512
  13.  
  14. enum { PHASE62, PHASE44, PHASE26 };
  15.  
  16. enum { PHASE06, PHASE24, PHASE42, PHASE60 };
  17.  
  18.  
  19.  
  20. static char                *gStartOfBinhex = "(This file must be converted with BinHex";
  21. static char                *gBinhexHeader = "(This file must be converted with BinHex 4.0)";
  22. static char                *gEndOfPart = "--- end of part";
  23. static char                gBinHexCodes[256],*gBinHexChars = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
  24. static unsigned char    *gNextHexCharPtr;
  25. static unsigned char    gCurrentReadByte,gCurrentWriteByte;
  26. static unsigned char    gPrevChar,gTheByte;
  27. static int                gChar90Count;
  28. static int                gHexPhase,gLeftIndex,gRightIndex;
  29. static unsigned int        gCRC;
  30. static char                gWriteBuffer[BUFFSIZE],gReadBuffer[BUFFSIZE];
  31. static long                gHexBytesLeftToRead,gReadBufferBytesLeft;
  32. static long                gWriteBufferIndex,gBuffer64Count;
  33. static int                gWriteFRefNum,gReadFRefNum;
  34. static char                gSaveToDisk,gReadFromDisk;
  35. static Handle            gBinhexHandle;
  36. static long                gBinhexHandleSize,gBinhexIndex;
  37. static Ptr                gHexReadPtr;
  38.  
  39.  
  40.  
  41. static int GetNextReadByte(void);
  42. static int ShiftReadBuffer(void);
  43. static void CalcCRC(unsigned char theByte);
  44. static int WriteBinhexBuffer(void);
  45. static int PutByteToBinhexBuffer(void);
  46. static int FlushBinhexBuffer(void);
  47. static int SkipBreak(void);
  48. static int SkipJunkHexData(void);
  49. static int ExtractByteFromHexData(void);
  50. static int GetNextLogicalHexDataByte(char doCRC);
  51. static int FindStartOfHexData(void);
  52. static int FindEndOfHexData(void);
  53. static void SetupBinhexDataArray(void);
  54.  
  55.  
  56.  
  57. static int GetNextReadByte(void)
  58. {
  59. register int    errCode;
  60.  
  61.     errCode = noErr;
  62.     
  63.     
  64.     if (gHexBytesLeftToRead <= 0)
  65.     {
  66.         sprintf(errorMessage,"GetNextReadByte: early end-of-file encountered");
  67.         errCode = EARLYEOF;
  68.         goto EXITPOINT;
  69.     }
  70.     
  71.     if (gReadBufferBytesLeft <= 0)
  72.     {
  73.         if (gHexBytesLeftToRead > BUFFSIZE)
  74.             gReadBufferBytesLeft = BUFFSIZE;
  75.         else
  76.             gReadBufferBytesLeft = gHexBytesLeftToRead;
  77.         
  78.         if (gReadFromDisk)
  79.         {
  80.             errCode = FSRead(gReadFRefNum,&gReadBufferBytesLeft,(Ptr) gReadBuffer);
  81.             
  82.             if (errCode != noErr)
  83.             {
  84.                 sprintf(errorMessage,"GetNextReadByte: FSRead() error %d",errCode);
  85.                 goto EXITPOINT;
  86.             }
  87.         }
  88.         
  89.         else
  90.         {
  91.             BlockMove(gHexReadPtr,gReadBuffer,gReadBufferBytesLeft);
  92.             
  93.             gHexReadPtr += gReadBufferBytesLeft;
  94.         }
  95.         
  96.         gNextHexCharPtr = (unsigned char *) gReadBuffer;
  97.     }
  98.     
  99.     
  100.     gCurrentReadByte = *gNextHexCharPtr++;
  101.     gReadBufferBytesLeft--;
  102.     gHexBytesLeftToRead--;
  103.  
  104.  
  105. EXITPOINT:
  106.     
  107.     return(errCode);
  108. }
  109.  
  110.  
  111.  
  112.  
  113.  
  114. static int ShiftReadBuffer(void)
  115. {
  116. register int    errCode;
  117. long            byteCount;
  118.  
  119.     errCode = noErr;
  120.     
  121.     if (gHexBytesLeftToRead <= 0)
  122.     {
  123.         sprintf(errorMessage,"ShiftReadBuffer: early end-of-file encountered");
  124.         errCode = EARLYEOF;
  125.         goto EXITPOINT;
  126.     }
  127.     
  128.     if (gReadBufferBytesLeft > 0)
  129.         BlockMove((Ptr) gNextHexCharPtr,(Ptr) gReadBuffer,gReadBufferBytesLeft);
  130.     
  131.     if (gHexBytesLeftToRead > BUFFSIZE - gReadBufferBytesLeft)
  132.         byteCount = BUFFSIZE - gReadBufferBytesLeft;
  133.     else
  134.         byteCount = gHexBytesLeftToRead;
  135.     
  136.     
  137.     if (gReadFromDisk)
  138.     {
  139.         errCode = FSRead(gReadFRefNum,&byteCount,(Ptr) gReadBuffer + gReadBufferBytesLeft);
  140.     
  141.         if (errCode != noErr)
  142.         {
  143.             sprintf(errorMessage,"ShiftReadBuffer: FSRead() error %d",errCode);
  144.             goto EXITPOINT;
  145.         }
  146.     }
  147.     
  148.     else
  149.     {
  150.         BlockMove(gHexReadPtr,gReadBuffer + gReadBufferBytesLeft,byteCount);
  151.         
  152.         gHexReadPtr += byteCount;
  153.     }
  154.     
  155.     gNextHexCharPtr = (unsigned char *) gReadBuffer;
  156.     gReadBufferBytesLeft += byteCount;
  157.     
  158. EXITPOINT:
  159.  
  160.     return(errCode);
  161. }
  162.  
  163.  
  164.  
  165.  
  166.  
  167. static void CalcCRC(unsigned char theByte)
  168. {
  169. register unsigned int    tempCRC;
  170. register unsigned char    tempByte;
  171.  
  172.     tempCRC = gCRC;
  173.     tempByte = theByte;
  174.     
  175.     asm
  176.     {
  177.         lsl.b    #1,tempByte
  178.         roxl.w    #1,tempCRC
  179.         bcc        @noXOR1
  180.         
  181.         eor.w    #0x1021,tempCRC
  182.         
  183.     @noXOR1
  184.         lsl.b    #1,tempByte
  185.         roxl.w    #1,tempCRC
  186.         bcc        @noXOR2
  187.         
  188.         eor.w    #0x1021,tempCRC
  189.         
  190.     @noXOR2
  191.         lsl.b    #1,tempByte
  192.         roxl.w    #1,tempCRC
  193.         bcc        @noXOR3
  194.         
  195.         eor.w    #0x1021,tempCRC
  196.         
  197.     @noXOR3
  198.         lsl.b    #1,tempByte
  199.         roxl.w    #1,tempCRC
  200.         bcc        @noXOR4
  201.         
  202.         eor.w    #0x1021,tempCRC
  203.         
  204.     @noXOR4
  205.         lsl.b    #1,tempByte
  206.         roxl.w    #1,tempCRC
  207.         bcc        @noXOR5
  208.         
  209.         eor.w    #0x1021,tempCRC
  210.         
  211.     @noXOR5
  212.         lsl.b    #1,tempByte
  213.         roxl.w    #1,tempCRC
  214.         bcc        @noXOR6
  215.         
  216.         eor.w    #0x1021,tempCRC
  217.         
  218.     @noXOR6
  219.         lsl.b    #1,tempByte
  220.         roxl.w    #1,tempCRC
  221.         bcc        @noXOR7
  222.         
  223.         eor.w    #0x1021,tempCRC
  224.         
  225.     @noXOR7
  226.         lsl.b    #1,tempByte
  227.         roxl.w    #1,tempCRC
  228.         bcc        @done
  229.         
  230.         eor.w    #0x1021,tempCRC
  231.         
  232.     @done
  233.     }
  234.     
  235.     gCRC = tempCRC;
  236. }
  237.  
  238.  
  239.  
  240.  
  241.  
  242. static int WriteBinhexBuffer(void)
  243. {
  244. register int    errCode;
  245.  
  246.     errCode = noErr;
  247.     
  248.     if (gSaveToDisk)
  249.     {
  250.         errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  251.         
  252.         if (errCode != noErr)
  253.             sprintf(errorMessage,"WriteBinhexBuffer: FSWrite() error %d",errCode);
  254.     }
  255.     
  256.     else if (gBinhexHandle)
  257.     {
  258.         if (gBinhexIndex + gWriteBufferIndex >= gBinhexHandleSize)
  259.         {
  260.             SetHandleSize(gBinhexHandle,gBinhexIndex + gWriteBufferIndex + BUFFSIZE);
  261.             
  262.             errCode = MemError();
  263.             
  264.             gBinhexHandleSize = GetHandleSize(gBinhexHandle);
  265.             
  266.             if (errCode != noErr || gBinhexIndex + gWriteBufferIndex > gBinhexHandleSize)
  267.             {
  268.                 if (errCode == noErr)
  269.                     errCode = memFullErr;
  270.                 
  271.                 sprintf(errorMessage,"WriteBinhexBuffer: SetHandleSize(gBinhexHandle,%ld) error %d",gBinhexIndex + gWriteBufferIndex + BUFFSIZE,errCode);
  272.             }
  273.         }
  274.         
  275.         if (gBinhexIndex + gWriteBufferIndex <= gBinhexHandleSize && errCode == noErr)
  276.         {
  277.             HLock(gBinhexHandle);
  278.             BlockMove(gWriteBuffer,*gBinhexHandle + gBinhexIndex,gWriteBufferIndex);
  279.             HUnlock(gBinhexHandle);
  280.             
  281.             gBinhexIndex += gWriteBufferIndex;
  282.         }
  283.     }
  284.  
  285.  
  286.     gWriteBufferIndex = 0;
  287.     
  288.     return(errCode);
  289. }
  290.  
  291.  
  292.  
  293.  
  294. static int PutByteToBinhexBuffer(void)
  295. {
  296. register int            errCode;
  297. register unsigned char    origByte;
  298.  
  299.     errCode = noErr;
  300.     origByte = gCurrentWriteByte;
  301.     
  302.     CalcCRC(gCurrentWriteByte);
  303.         
  304.     do
  305.     {
  306.         do
  307.         {
  308.             if (gWriteBufferIndex >= BUFFSIZE - 2)
  309.             {
  310.                 errCode = WriteBinhexBuffer();
  311.                 
  312.                 if (errCode != noErr)
  313.                     goto EXITPOINT;
  314.             }
  315.             
  316.             
  317.             if (gHexPhase == PHASE06)
  318.             {
  319.                 gLeftIndex = (gCurrentWriteByte >> 2) & 0x003F;
  320.                 gRightIndex = gCurrentWriteByte;
  321.                 
  322.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  323.                 
  324.                 gHexPhase = PHASE24;
  325.             }
  326.             
  327.             else if (gHexPhase == PHASE24)
  328.             {
  329.                 gLeftIndex = ((gRightIndex << 4) & 0x0030) | ((gCurrentWriteByte >> 4) & 0x000F);
  330.                 gRightIndex = gCurrentWriteByte;
  331.                 
  332.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  333.                 
  334.                 gHexPhase = PHASE42;
  335.             }
  336.             
  337.             else if (gHexPhase == PHASE42)
  338.             {
  339.                 gLeftIndex = ((gRightIndex << 2) & 0x003C) | ((gCurrentWriteByte >> 6) & 0x0003);
  340.                 gRightIndex = gCurrentWriteByte;
  341.                 
  342.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  343.                 
  344.                 gHexPhase = PHASE60;
  345.             }
  346.             
  347.             else if (gHexPhase == PHASE60)
  348.             {
  349.                 gLeftIndex = gRightIndex & 0x003F;
  350.                 
  351.                 gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  352.                 
  353.                 gHexPhase = PHASE06;
  354.             }
  355.             
  356.             if (++gBuffer64Count >= 64)
  357.             {
  358.                 gWriteBuffer[gWriteBufferIndex++] = '\r';
  359.                 gBuffer64Count = 0;
  360.             }
  361.             
  362.         } while (gHexPhase == PHASE06);
  363.         
  364.         if (origByte == RLFLAG)
  365.         {
  366.             if (gCurrentWriteByte == RLFLAG)
  367.                 gCurrentWriteByte = 0;
  368.             else
  369.                 origByte = 0;
  370.         }
  371.         
  372.     } while (origByte == RLFLAG);
  373.     
  374. EXITPOINT:
  375.  
  376.     return(errCode);
  377. }
  378.  
  379.  
  380.  
  381.  
  382.  
  383. static int FlushBinhexBuffer(void)
  384. {
  385. int        errCode;
  386.  
  387.     errCode = 0;
  388.  
  389.     if (gWriteBufferIndex >= BUFFSIZE - 2)
  390.     {
  391.         errCode = WriteBinhexBuffer();
  392.     }
  393.     
  394.     gTheByte = 0;
  395.     
  396.     if (gHexPhase == PHASE24)
  397.     {
  398.         gLeftIndex = ((gRightIndex << 4) & 0x0030) | ((gTheByte >> 4) & 0x000F);
  399.         gRightIndex = gTheByte;
  400.         
  401.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  402.     }
  403.     
  404.     else if (gHexPhase == PHASE42)
  405.     {
  406.         gLeftIndex = ((gRightIndex << 2) & 0x003C) | ((gTheByte >> 6) & 0x0003);
  407.         gRightIndex = gTheByte;
  408.         
  409.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  410.     }
  411.     
  412.     else if (gHexPhase == PHASE60)
  413.     {
  414.         gLeftIndex = gRightIndex & 0x003F;
  415.         
  416.         gWriteBuffer[gWriteBufferIndex++] = gBinHexChars[gLeftIndex];
  417.     }
  418.     
  419.     
  420.     errCode = WriteBinhexBuffer();
  421.     
  422.  
  423. EXITPOINT:
  424.  
  425.     return(errCode);
  426. }
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435. static int SkipBreak(void)
  436. {
  437. register int            errCode,dashCount;
  438. register unsigned char     *s1,*s2;
  439.     
  440.     
  441.     errCode = noErr;
  442.     
  443.     if (gCurrentReadByte == '-')
  444.     {
  445.         if (gReadBufferBytesLeft < strlen(gEndOfPart))
  446.         {
  447.             errCode = ShiftReadBuffer();
  448.             
  449.             if (errCode != noErr)
  450.                 goto EXITPOINT;
  451.         }
  452.         
  453.         s1 = (unsigned char *) gEndOfPart + 1L;
  454.         s2 = gNextHexCharPtr;
  455.         
  456.         while (*s1 == *s2 && *s1)
  457.         {
  458.             s1++;
  459.             s2++;
  460.         }
  461.         
  462.         if (*s1 == 0)
  463.         {
  464.             gNextHexCharPtr += strlen(gEndOfPart);
  465.             gReadBufferBytesLeft -= strlen(gEndOfPart);
  466.             gHexBytesLeftToRead -= strlen(gEndOfPart);
  467.             
  468.             if ((errCode = GetNextReadByte()) != noErr)
  469.                 goto EXITPOINT;
  470.             
  471.             dashCount = 0;
  472.             
  473.             while (dashCount < 3)
  474.             {
  475.                 if (gCurrentReadByte == '-')
  476.                     dashCount++;
  477.                 else
  478.                     dashCount = 0;
  479.                 
  480.                 if ((errCode = GetNextReadByte()) != noErr)
  481.                     goto EXITPOINT;
  482.             }
  483.             
  484.             dashCount = 0;
  485.             
  486.             while (dashCount < 3)
  487.             {
  488.                 if (gCurrentReadByte == '-')
  489.                     dashCount++;
  490.                 else
  491.                     dashCount = 0;
  492.                 
  493.                 if ((errCode = GetNextReadByte()) != noErr)
  494.                     goto EXITPOINT;
  495.             }
  496.             
  497.             errCode = SkipJunkHexData();
  498.         }
  499.     }
  500.  
  501. EXITPOINT:
  502.  
  503.     return(errCode);
  504. }
  505.  
  506.  
  507.  
  508.  
  509. static int SkipJunkHexData(void)
  510. {
  511. register int    errCode;
  512. register unsigned char     ch;
  513.  
  514.     errCode = noErr;
  515.     
  516.     ch = gCurrentReadByte;
  517.     
  518.     if (ch == CR || ch == LF || ch == SPACE || ch == TAB)
  519.     {
  520.         do
  521.         {
  522.             if ((errCode = GetNextReadByte()) != noErr)
  523.                 goto EXITPOINT;
  524.             
  525.             ch = gCurrentReadByte;
  526.             
  527.         } while (ch == CR || ch == LF || ch == SPACE || ch == TAB);
  528.         
  529.         if (gCurrentReadByte == '-')
  530.             errCode = SkipBreak();
  531.     }
  532.  
  533. EXITPOINT:
  534.     
  535.     return(errCode);
  536. }
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543. static int ExtractByteFromHexData(void)
  544. {
  545. register int        errCode;
  546.  
  547.  
  548.     gLeftIndex = gRightIndex;
  549.     
  550.     if ((errCode = GetNextReadByte()) != noErr)
  551.         goto EXITPOINT;
  552.     
  553.     if ((errCode = SkipJunkHexData()) != noErr)
  554.         goto EXITPOINT;
  555.     
  556.     
  557.     if (gCurrentReadByte == ':')
  558.     {
  559.         sprintf(errorMessage,"ExtractByteFromHexData: found early ':' end-of-file marker");
  560.         errCode = EARLYEOF;
  561.         goto EXITPOINT;
  562.     }
  563.     
  564.     
  565.     gRightIndex = gBinHexCodes[gCurrentReadByte];
  566.  
  567.     if (gRightIndex >= 64)
  568.     {
  569.         sprintf(errorMessage,"ExtractByteFromHexData: found bad binhex character '%c'",gCurrentReadByte);
  570.         errCode = BADHEXCHAR;
  571.         goto EXITPOINT;
  572.     }
  573.     
  574.     
  575.     if (gHexPhase == PHASE62)
  576.     {
  577.         if ((errCode = GetNextReadByte()) != noErr)
  578.             goto EXITPOINT;
  579.         
  580.         if ((errCode = SkipJunkHexData()) != noErr)
  581.             goto EXITPOINT;
  582.         
  583.         gLeftIndex = gRightIndex;
  584.         
  585.         if (gCurrentReadByte == ':')
  586.         {
  587.             sprintf(errorMessage,"ExtractByteFromHexData: found early ':' end-of-file marker");
  588.             errCode = EARLYEOF;
  589.             goto EXITPOINT;
  590.         }
  591.         
  592.         
  593.         gRightIndex = gBinHexCodes[gCurrentReadByte];
  594.     
  595.         if (gRightIndex >= 64)
  596.         {
  597.             sprintf(errorMessage,"ExtractByteFromHexData: found bad binhex character '%c'",gCurrentReadByte);
  598.             errCode = BADHEXCHAR;
  599.             goto EXITPOINT;
  600.         }
  601.         
  602.         gTheByte = ((gLeftIndex << 2) & 0xFC) | ((gRightIndex >> 4) & 0x03);
  603.         
  604.         gHexPhase = PHASE44;
  605.     }
  606.     
  607.     else if (gHexPhase == PHASE44)
  608.     {
  609.         gTheByte = ((gLeftIndex << 4) & 0xF0) | ((gRightIndex >> 2) & 0x0F);
  610.         
  611.         gHexPhase = PHASE26;
  612.     }
  613.     
  614.     else if (gHexPhase == PHASE26)
  615.     {
  616.         gTheByte = ((gLeftIndex << 6) & 0xC0) | (gRightIndex & 0x3F);
  617.         
  618.         gHexPhase = PHASE62;
  619.     }
  620.  
  621.  
  622. EXITPOINT:
  623.     
  624.     return(errCode);
  625. }
  626.  
  627.  
  628.  
  629.  
  630. static int GetNextLogicalHexDataByte(char doCRC)
  631. {
  632. register int        errCode;
  633.  
  634.     errCode = noErr;
  635.     
  636.     if (gChar90Count > 0)
  637.     {
  638.         gTheByte = gPrevChar;
  639.         gChar90Count--;
  640.         
  641.         if (doCRC)
  642.             CalcCRC(gTheByte);
  643.         else
  644.             CalcCRC(0);
  645.     }
  646.     
  647.     else
  648.     {
  649.         do
  650.         {
  651.             errCode = ExtractByteFromHexData();
  652.             
  653.             if (gTheByte != RLFLAG)
  654.                 break;
  655.             
  656.             else
  657.             {
  658.                 errCode = ExtractByteFromHexData();
  659.                 
  660.                 if (errCode != noErr)
  661.                     goto EXITPOINT;
  662.                 
  663.                 if (gTheByte == 0)
  664.                 {
  665.                     gTheByte = RLFLAG;
  666.                     break;
  667.                 }
  668.                 
  669.                 else if (gTheByte >= 2)
  670.                 {
  671.                     gChar90Count = gTheByte - 2;
  672.                     gTheByte = gPrevChar;
  673.                     break;
  674.                 }
  675.             }
  676.         
  677.         } while (TRUE);
  678.         
  679.         
  680.         gPrevChar = gTheByte;
  681.         
  682.         if (doCRC)
  683.             CalcCRC(gTheByte);
  684.         else
  685.             CalcCRC(0);
  686.     }
  687.     
  688. EXITPOINT:
  689.  
  690.     return(errCode);
  691. }
  692.  
  693.  
  694.  
  695.  
  696. static int FindStartOfHexData(void)
  697. {
  698. register int    errCode,i;
  699. char            foundStart;
  700.  
  701.     errCode = noErr;
  702.     
  703.     foundStart = FALSE;
  704.     
  705.     if ((errCode = GetNextReadByte()) != noErr)
  706.         goto EXITPOINT;
  707.     
  708.     while (!foundStart)
  709.     {
  710.         while (gCurrentReadByte != '(')
  711.         {
  712.             if ((errCode = GetNextReadByte()) != noErr)
  713.                 goto EXITPOINT;
  714.         }
  715.         
  716.         i = 0;
  717.         
  718.         while (gStartOfBinhex[i] && gCurrentReadByte == gStartOfBinhex[i])
  719.         {
  720.             if ((errCode = GetNextReadByte()) != noErr)
  721.                 goto EXITPOINT;
  722.             
  723.             i++;
  724.         }
  725.         
  726.         
  727.         if (gStartOfBinhex[i] == 0)
  728.         {
  729.             while (gCurrentReadByte != ':')
  730.             {
  731.                 if ((errCode = GetNextReadByte()) != noErr)
  732.                     goto EXITPOINT;
  733.             }
  734.             
  735.             foundStart = TRUE;
  736.         }
  737.     }
  738.     
  739.     gHexPhase = PHASE62;
  740.     gPrevChar = 0;
  741.  
  742. EXITPOINT:
  743.  
  744.     if (errCode == EARLYEOF)
  745.         sprintf(errorMessage,"FindStartOfHexData: couldn't find start of binhex data, '%s'",gBinhexHeader);
  746.     
  747.     return(errCode);
  748. }
  749.  
  750.  
  751.  
  752.  
  753. static int    FindEndOfHexData(void)
  754. {
  755. register int    errCode;
  756.  
  757.     errCode = noErr;
  758.  
  759.     SkipJunkHexData();
  760.     
  761.     if ((errCode = GetNextReadByte()) != noErr)
  762.         goto EXITPOINT;
  763.     
  764.     
  765.     while (gCurrentReadByte == '!')
  766.     {
  767.         SkipJunkHexData();
  768.         
  769.         if ((errCode = GetNextReadByte()) != noErr)
  770.             goto EXITPOINT;
  771.     }
  772.     
  773.     if (gCurrentReadByte != ':')
  774.     {
  775.         sprintf(errorMessage,"FindEndOfHexData: can't find ':' end-of-file marker");
  776.         errCode = BADEOF;
  777.     }
  778.  
  779. EXITPOINT:
  780.  
  781.     if (errCode == EARLYEOF)
  782.         sprintf(errorMessage,"FindEndOfHexData: can't find ':' end-of-file marker");
  783.     
  784.     return(errCode);
  785. }
  786.  
  787.  
  788.  
  789. static void SetupBinhexDataArray(void)
  790. {
  791. register int        i;
  792.  
  793.     for (i=0;i<256;i++)
  794.         gBinHexCodes[i] = 64;
  795.     
  796.     for (i=0;i<64;i++)
  797.         gBinHexCodes[gBinHexChars[i]] = i;
  798. }
  799.  
  800.  
  801.  
  802.  
  803.  
  804. int ConvertFromBinhex(char readFromDisk,Ptr theBinhexPtr,long dataLength)
  805. {
  806. register unsigned long    i;
  807. int                        errCode;
  808. unsigned int            crc;
  809. unsigned int            theFlags;
  810. unsigned long            dataForkLength,resForkLength;
  811. char                    fileName[256];
  812. unsigned char            nameLength;
  813. long                    theType,theCreator;
  814. sys67SFReply             inSys67SFReply,outSys67SFReply;
  815. SFTypeList                theSFTypes;
  816.  
  817.     gReadFromDisk = readFromDisk;
  818.     
  819.     gReadFRefNum = 0;
  820.     gWriteFRefNum = 0;
  821.     gReadBufferBytesLeft = 0L;
  822.     gHexBytesLeftToRead = 0L;
  823.     gChar90Count = 0;
  824.     gPrevChar = 0;
  825.     
  826.     SetupBinhexDataArray();
  827.     
  828.     
  829.     if (gReadFromDisk)
  830.     {
  831.         theSFTypes[0] = 'TEXT';
  832.         
  833.         errCode = SelectInputFile(&inSys67SFReply,&theSFTypes,1);
  834.         
  835.         if (errCode != noErr)
  836.             goto NOBINHEXERR;
  837.         
  838.         
  839.         errCode = GetDataForkLength(&inSys67SFReply,&gHexBytesLeftToRead);
  840.         
  841.         if (errCode != noErr)
  842.             goto BINHEXERR;
  843.         
  844.         
  845.         errCode = OpenDataFork(&inSys67SFReply,&gReadFRefNum);
  846.         
  847.         if (errCode != noErr)
  848.             goto BINHEXERR;
  849.     }
  850.     
  851.     else
  852.     {
  853.         if (theBinhexPtr == 0L)
  854.         {
  855.             sprintf(errorMessage,"ConvertFromBinhex: Bad parameter, theBinhexPtr == 0L");
  856.             errCode = BADPARAM;
  857.             goto BINHEXERR;
  858.         }
  859.         
  860.         gHexReadPtr = theBinhexPtr;
  861.         
  862.         gHexBytesLeftToRead = dataLength;
  863.     }
  864.     
  865.     
  866.     errCode = FindStartOfHexData();
  867.     
  868.     if (errCode != noErr)
  869.         goto BINHEXERR;
  870.     
  871.     
  872.     gCRC = 0;
  873.     
  874.     errCode = GetNextLogicalHexDataByte(TRUE);
  875.     
  876.     if (errCode != noErr)
  877.         goto BINHEXERR;
  878.     
  879.     
  880.     nameLength = gTheByte;
  881.     
  882.     for (i=0;i<nameLength && errCode == noErr;i++)
  883.     {
  884.         errCode = GetNextLogicalHexDataByte(TRUE);
  885.         
  886.         if (errCode != noErr)
  887.             goto BINHEXERR;
  888.         
  889.         fileName[i] = gTheByte;
  890.     }
  891.     
  892.     errCode = GetNextLogicalHexDataByte(TRUE);
  893.     
  894.     if (errCode != noErr)
  895.         goto BINHEXERR;
  896.     
  897.     if (gTheByte != 0)
  898.     {
  899.         sprintf(errorMessage,"ConvertFromBinhex: can't find 0x00 name terminator in header");
  900.         errCode = NOZERO;
  901.         goto BINHEXERR;
  902.     }
  903.     
  904.     fileName[i] = gTheByte;
  905.  
  906.     theType = 0L;
  907.     
  908.     for (i=0;i<4 && errCode == noErr;i++)
  909.     {
  910.         errCode = GetNextLogicalHexDataByte(TRUE);
  911.         
  912.         if (errCode != noErr)
  913.             goto BINHEXERR;
  914.         
  915.         theType = (theType << 8) | gTheByte;
  916.     }
  917.     
  918.  
  919.     theCreator = 0L;
  920.     
  921.     for (i=0;i<4 && errCode == noErr;i++)
  922.     {
  923.         errCode = GetNextLogicalHexDataByte(TRUE);
  924.         
  925.         if (errCode != noErr)
  926.             goto BINHEXERR;
  927.         
  928.         theCreator = (theCreator << 8) | gTheByte;
  929.     }
  930.     
  931.     
  932.     errCode = GetNextLogicalHexDataByte(TRUE);
  933.     
  934.     if (errCode != noErr)
  935.         goto BINHEXERR;
  936.     
  937.     theFlags = gTheByte;
  938.     
  939.     errCode = GetNextLogicalHexDataByte(TRUE);
  940.     
  941.     if (errCode != noErr)
  942.         goto BINHEXERR;
  943.     
  944.     theFlags = (theFlags << 8) | gTheByte;
  945.     
  946.     
  947.     dataForkLength = 0L;
  948.     
  949.     for (i=0;i<4 && errCode == noErr;i++)
  950.     {
  951.         errCode = GetNextLogicalHexDataByte(TRUE);
  952.         
  953.         if (errCode != noErr)
  954.             goto BINHEXERR;
  955.         
  956.         dataForkLength = (dataForkLength << 8) | gTheByte;
  957.     }
  958.     
  959.     
  960.     resForkLength = 0L;
  961.     
  962.     for (i=0;i<4 && errCode == noErr;i++)
  963.     {
  964.         errCode = GetNextLogicalHexDataByte(TRUE);
  965.         
  966.         if (errCode != noErr)
  967.             goto BINHEXERR;
  968.         
  969.         resForkLength = (resForkLength << 8) | gTheByte;
  970.     }
  971.     
  972.     
  973.     errCode = GetNextLogicalHexDataByte(FALSE);
  974.     
  975.     if (errCode != noErr)
  976.         goto BINHEXERR;
  977.     
  978.     crc = gTheByte;
  979.     
  980.     errCode = GetNextLogicalHexDataByte(FALSE);
  981.     
  982.     if (errCode != noErr)
  983.         goto BINHEXERR;
  984.     
  985.     crc = (crc << 8) | gTheByte;
  986.     
  987.     if (crc != gCRC)
  988.     {
  989.         sprintf(errorMessage,"ConvertFromBinhex: bad header CRC 0x%04X <> 0x%04X",crc,gCRC);
  990.         goto BINHEXERR;
  991.     }
  992.     
  993.     
  994.     
  995.     errCode = SelectOutputFile(&outSys67SFReply,fileName);
  996.     
  997.     if (errCode != noErr)
  998.         goto NOBINHEXERR;
  999.     
  1000.     
  1001.     errCode = OpenAndZeroDataFork(theType,theCreator,&outSys67SFReply,&gWriteFRefNum);
  1002.     
  1003.     if (errCode != noErr)
  1004.         goto BINHEXERR;
  1005.     
  1006.     
  1007.     gWriteBufferIndex = 0;
  1008.     gCRC = 0;
  1009.     
  1010.     for (i=0;i<dataForkLength;i++)
  1011.     {
  1012.         errCode = GetNextLogicalHexDataByte(TRUE);
  1013.         
  1014.         if (errCode != noErr)
  1015.             goto BINHEXERR;
  1016.         
  1017.         
  1018.         if (gWriteBufferIndex >= BUFFSIZE)
  1019.         {
  1020.             if (gWriteBufferIndex > 0)
  1021.                 errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1022.             
  1023.             if (errCode != noErr)
  1024.             {
  1025.                 sprintf(errorMessage,"ConvertFromBinhex: data fork FSWrite() error %d",errCode);
  1026.                 goto BINHEXERR;
  1027.             }
  1028.             
  1029.             gWriteBufferIndex = 0;
  1030.         }
  1031.         
  1032.         gWriteBuffer[gWriteBufferIndex++] = gTheByte;
  1033.     }
  1034.     
  1035.     
  1036.     if (gWriteBufferIndex > 0)
  1037.     {
  1038.         errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1039.         
  1040.         if (errCode != noErr)
  1041.         {
  1042.             sprintf(errorMessage,"ConvertFromBinhex: data fork FSWrite() error %d",errCode);
  1043.             goto BINHEXERR;
  1044.         }
  1045.         
  1046.         gWriteBufferIndex = 0;
  1047.     }
  1048.     
  1049.     errCode = FSClose(gWriteFRefNum);
  1050.     gWriteFRefNum = 0;
  1051.     
  1052.     if (errCode != noErr)
  1053.     {
  1054.         sprintf(errorMessage,"ConvertFromBinhex: FSClose() error %d",errCode);
  1055.         goto BINHEXERR;
  1056.     }
  1057.     
  1058.     
  1059.     errCode = GetNextLogicalHexDataByte(FALSE);
  1060.     
  1061.     if (errCode != noErr)
  1062.         goto BINHEXERR;
  1063.     
  1064.     crc = gTheByte;
  1065.     
  1066.     errCode = GetNextLogicalHexDataByte(FALSE);
  1067.     
  1068.     if (errCode != noErr)
  1069.         goto BINHEXERR;
  1070.     
  1071.     crc = (crc << 8) | gTheByte;
  1072.     
  1073.     if (crc != gCRC)
  1074.     {
  1075.         sprintf(errorMessage,"ConvertFromBinhex: bad data fork CRC 0x%04X <> 0x%04X",crc,gCRC);
  1076.         goto BINHEXERR;
  1077.     }
  1078.     
  1079.     
  1080.     
  1081.  
  1082.     errCode = OpenAndZeroResourceFork(theType,theCreator,&outSys67SFReply,&gWriteFRefNum);
  1083.     
  1084.     if (errCode != noErr)
  1085.         goto BINHEXERR;
  1086.     
  1087.     
  1088.     gWriteBufferIndex = 0;
  1089.     gCRC = 0;
  1090.     
  1091.     for (i=0;i<resForkLength;i++)
  1092.     {
  1093.         errCode = GetNextLogicalHexDataByte(TRUE);
  1094.         
  1095.         if (errCode != noErr)
  1096.             goto BINHEXERR;
  1097.         
  1098.         
  1099.         if (gWriteBufferIndex >= BUFFSIZE)
  1100.         {
  1101.             if (gWriteBufferIndex > 0)
  1102.                 errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1103.             
  1104.             if (errCode != noErr)
  1105.             {
  1106.                 sprintf(errorMessage,"ConvertFromBinhex: resource fork FSWrite() error %d",errCode);
  1107.                 goto BINHEXERR;
  1108.             }
  1109.             
  1110.             gWriteBufferIndex = 0;
  1111.         }
  1112.         
  1113.         gWriteBuffer[gWriteBufferIndex++] = gTheByte;
  1114.     }
  1115.     
  1116.     
  1117.     if (gWriteBufferIndex > 0)
  1118.     {
  1119.         errCode = FSWrite(gWriteFRefNum,&gWriteBufferIndex,(Ptr) gWriteBuffer);
  1120.         
  1121.         if (errCode != noErr)
  1122.         {
  1123.             sprintf(errorMessage,"ConvertFromBinhex: resource fork FSWrite() error %d",errCode);
  1124.             goto BINHEXERR;
  1125.         }
  1126.         
  1127.         gWriteBufferIndex = 0;
  1128.     }
  1129.     
  1130.     errCode = FSClose(gWriteFRefNum);
  1131.     gWriteFRefNum = 0;
  1132.     
  1133.     if (errCode != noErr)
  1134.     {
  1135.         sprintf(errorMessage,"ConvertFromBinhex: FSClose() error %d",errCode);
  1136.         goto BINHEXERR;
  1137.     }
  1138.     
  1139.     
  1140.     errCode = GetNextLogicalHexDataByte(FALSE);
  1141.     
  1142.     if (errCode != noErr)
  1143.         goto BINHEXERR;
  1144.     
  1145.     crc = gTheByte;
  1146.     
  1147.     errCode = GetNextLogicalHexDataByte(FALSE);
  1148.     
  1149.     if (errCode != noErr)
  1150.         goto BINHEXERR;
  1151.     
  1152.     crc = (crc << 8) | gTheByte;
  1153.     
  1154.     if (crc != gCRC)
  1155.     {
  1156.         sprintf(errorMessage,"ConvertFromBinhex: bad resource fork CRC 0x%04X <> 0x%04X",crc,gCRC);
  1157.         goto BINHEXERR;
  1158.     }
  1159.     
  1160.     errCode = FindEndOfHexData();
  1161.     
  1162.     if (errCode != noErr)
  1163.         goto BINHEXERR;
  1164.     
  1165.     
  1166.     errCode = SetSFTypeCreatorFlags(&outSys67SFReply,theType,theCreator,theFlags);
  1167.     
  1168.     if (errCode != noErr)
  1169.         goto BINHEXERR;
  1170.     
  1171.     
  1172.     
  1173.     if (errCode == noErr)
  1174.         goto NOBINHEXERR;
  1175.     
  1176.     
  1177.     
  1178.     
  1179. BINHEXERR:
  1180.     
  1181.  
  1182. NOBINHEXERR:
  1183.  
  1184.     if (gReadFRefNum)
  1185.     {
  1186.         if (errCode == noErr)
  1187.         {
  1188.             errCode = FSClose(gReadFRefNum);
  1189.             
  1190.             if (errCode != noErr)
  1191.             {
  1192.                 ExtractSFFileName(&inSys67SFReply,fileName);
  1193.                 
  1194.                 sprintf(errorMessage,"ConvertFromBinhex: FSClose('%s') error %d",fileName,errCode);
  1195.             }
  1196.         }
  1197.         
  1198.         else
  1199.             FSClose(gReadFRefNum);
  1200.         
  1201.         gReadFRefNum = 0;
  1202.     }
  1203.     
  1204.     if (gWriteFRefNum)
  1205.     {
  1206.         if (errCode == noErr)
  1207.         {
  1208.             errCode = FSClose(gWriteFRefNum);
  1209.             
  1210.             if (errCode != noErr)
  1211.             {
  1212.                 ExtractSFFileName(&outSys67SFReply,fileName);
  1213.                 
  1214.                 sprintf(errorMessage,"ConvertFromBinhex: FSClose('%s') error %d",fileName,errCode);
  1215.             }
  1216.         }
  1217.         
  1218.         else
  1219.             FSClose(gWriteFRefNum);
  1220.             
  1221.         gWriteFRefNum = 0;
  1222.     }
  1223.     
  1224.     if (errCode == USERCANCEL)
  1225.         errCode = noErr;
  1226.     
  1227.     return(errCode);
  1228. }
  1229.  
  1230.  
  1231.  
  1232.  
  1233. int ConvertToBinhex(char saveToDisk,Handle    *theBinhexHandle)
  1234. {
  1235. long                i;
  1236. long                dataForkLength,resForkLength;
  1237. int                    errCode;
  1238. sys67SFReply         inSys67SFReply,outSys67SFReply;
  1239. unsigned int        crc;
  1240. unsigned int        theFlags;
  1241. char                fileName[256];
  1242. unsigned char        nameLength;
  1243. long                theType,theCreator;
  1244. SFTypeList            theSFTypes;
  1245.  
  1246.     
  1247.     gReadFRefNum = 0;
  1248.     gWriteFRefNum = 0;
  1249.     
  1250.     gSaveToDisk = saveToDisk;
  1251.     
  1252.     gReadFromDisk = TRUE;
  1253.     
  1254.     if (!saveToDisk)
  1255.     {
  1256.         if (theBinhexHandle == 0L)
  1257.         {
  1258.             sprintf(errorMessage,"ConvertToBinhex: Bad parameter, theBinhexHandle == 0L");
  1259.             errCode = BADPARAM;
  1260.             goto BINHEXERR;
  1261.         }
  1262.         
  1263.         else
  1264.         {
  1265.             *theBinhexHandle = 0L;
  1266.             
  1267.             gBinhexHandle = NewHandle(BUFFSIZE);
  1268.             
  1269.             errCode = MemError();
  1270.             
  1271.             if (gBinhexHandle == 0L || errCode != noErr)
  1272.             {
  1273.                 if (errCode == noErr)
  1274.                     errCode = memFullErr;
  1275.                 
  1276.                 sprintf(errorMessage,"ConvertToBinhex: NewHandle() error %d",errCode);
  1277.                         
  1278.                 goto BINHEXERR;
  1279.             }
  1280.             
  1281.             gBinhexHandleSize = GetHandleSize(gBinhexHandle);
  1282.             gBinhexIndex = 0L;
  1283.         }
  1284.     }
  1285.  
  1286.     errCode = SelectInputFile(&inSys67SFReply,&theSFTypes,-1);
  1287.     
  1288.     if (errCode != noErr)
  1289.         goto NOBINHEXERR;
  1290.     
  1291.     errCode = GetSFTypeCreatorFlags(&inSys67SFReply,&theType,&theCreator,&theFlags);
  1292.     
  1293.     if (errCode != noErr)
  1294.         goto BINHEXERR;
  1295.     
  1296.     ExtractSFFileName(&inSys67SFReply,fileName);
  1297.     
  1298.     
  1299.     if (saveToDisk)
  1300.     {
  1301.         if (strlen(fileName) >= 27)
  1302.             fileName[27] = 0;
  1303.         
  1304.         mystrncat(fileName,".hqx",32);
  1305.         
  1306.         errCode = SelectOutputFile(&outSys67SFReply,fileName);
  1307.         
  1308.         if (errCode != noErr)
  1309.             goto NOBINHEXERR;
  1310.         
  1311.         
  1312.         errCode = OpenAndZeroDataFork(HEXTYPE,HEXCREATOR,&outSys67SFReply,&gWriteFRefNum);
  1313.         
  1314.         if (errCode != noErr)
  1315.             goto BINHEXERR;
  1316.     }
  1317.     
  1318.     gWriteBufferIndex = 0;
  1319.     
  1320.     mystrncpy(gWriteBuffer,gBinhexHeader,BUFFSIZE);
  1321.     gWriteBufferIndex = strlen(gWriteBuffer);
  1322.     
  1323.     gWriteBuffer[gWriteBufferIndex++] = '\r';
  1324.     gWriteBuffer[gWriteBufferIndex++] = ':';
  1325.     
  1326.     errCode = WriteBinhexBuffer();
  1327.     
  1328.     if (errCode != noErr)
  1329.         goto BINHEXERR;
  1330.     
  1331.     gWriteBufferIndex = 0;
  1332.     gCRC = 0;
  1333.     gBuffer64Count = 1;
  1334.     gHexPhase = PHASE06;
  1335.     
  1336.     ExtractSFFileName(&inSys67SFReply,fileName);
  1337.     nameLength = strlen(fileName);
  1338.     
  1339.     gCurrentWriteByte = (char) nameLength;
  1340.     
  1341.     if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1342.         goto BINHEXERR;
  1343.     
  1344.     
  1345.     for (i=0;i<=nameLength;i++)
  1346.     {
  1347.         gCurrentWriteByte = fileName[i];
  1348.         
  1349.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1350.             goto BINHEXERR;
  1351.     }
  1352.     
  1353.     
  1354.     errCode = GetSFTypeCreatorFlags(&inSys67SFReply,&theType,&theCreator,&theFlags);
  1355.     
  1356.     if (errCode != noErr)
  1357.         goto BINHEXERR;
  1358.     
  1359.     
  1360.     for (i=0;i<4;i++)
  1361.     {
  1362.         gCurrentWriteByte = (theType >> 24) & 0xFF;
  1363.         
  1364.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1365.             goto BINHEXERR;
  1366.         
  1367.         theType <<= 8;
  1368.     }
  1369.     
  1370.     
  1371.     for (i=0;i<4;i++)
  1372.     {
  1373.         gCurrentWriteByte = (theCreator >> 24) & 0xFF;
  1374.         
  1375.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1376.             goto BINHEXERR;
  1377.         
  1378.         theCreator <<= 8;
  1379.     }
  1380.     
  1381.     for (i=0;i<2;i++)
  1382.     {
  1383.         gCurrentWriteByte = (theFlags >> 8) & 0xFF;
  1384.         
  1385.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1386.             goto BINHEXERR;
  1387.         
  1388.         theFlags <<= 8;
  1389.     }
  1390.     
  1391.     
  1392.     errCode = GetDataForkLength(&inSys67SFReply,&dataForkLength);
  1393.     
  1394.     if (errCode != noErr)
  1395.         goto BINHEXERR;
  1396.     
  1397.     for (i=0;i<4;i++)
  1398.     {
  1399.         gCurrentWriteByte = (dataForkLength >> 24) & 0xFF;
  1400.         
  1401.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1402.             goto BINHEXERR;
  1403.         
  1404.         dataForkLength <<= 8;
  1405.     }
  1406.     
  1407.     
  1408.     errCode = GetResourceForkLength(&inSys67SFReply,&resForkLength);
  1409.     
  1410.     if (errCode != noErr)
  1411.         goto BINHEXERR;
  1412.     
  1413.     for (i=0;i<4;i++)
  1414.     {
  1415.         gCurrentWriteByte = (resForkLength >> 24) & 0xFF;
  1416.         
  1417.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1418.             goto BINHEXERR;
  1419.         
  1420.         resForkLength <<= 8;
  1421.     }
  1422.     
  1423.     CalcCRC(0);
  1424.     CalcCRC(0);
  1425.     
  1426.     crc = gCRC;
  1427.     
  1428.     for (i=0;i<2;i++)
  1429.     {
  1430.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1431.         
  1432.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1433.             goto BINHEXERR;
  1434.         
  1435.         crc <<= 8;
  1436.     }
  1437.     
  1438.     
  1439.     errCode = GetDataForkLength(&inSys67SFReply,&dataForkLength);
  1440.     
  1441.     if (errCode != noErr)
  1442.         goto BINHEXERR;
  1443.     
  1444.     errCode = OpenDataFork(&inSys67SFReply,&gReadFRefNum);
  1445.     
  1446.     if (errCode != noErr)
  1447.         goto BINHEXERR;
  1448.     
  1449.     gCRC = 0;
  1450.     gReadBufferBytesLeft = 0L;
  1451.     gHexBytesLeftToRead = dataForkLength;
  1452.     
  1453.     for (i=0;i<dataForkLength;i++)
  1454.     {
  1455.         if ((errCode = GetNextReadByte()) != noErr)
  1456.             goto BINHEXERR;
  1457.         
  1458.         gCurrentWriteByte = gCurrentReadByte;
  1459.         
  1460.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1461.             goto BINHEXERR;
  1462.     }
  1463.     
  1464.     if ((errCode = FSClose(gReadFRefNum)) != noErr)
  1465.     {
  1466.         gReadFRefNum = 0;
  1467.         sprintf(errorMessage,"ConvertFromBinhex: FSClose() error %d",errCode);
  1468.         goto BINHEXERR;
  1469.     }
  1470.     
  1471.     gReadFRefNum = 0;
  1472.     
  1473.     
  1474.     CalcCRC(0);
  1475.     CalcCRC(0);
  1476.     
  1477.     crc = gCRC;
  1478.     
  1479.     for (i=0;i<2;i++)
  1480.     {
  1481.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1482.         
  1483.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1484.             goto BINHEXERR;
  1485.         
  1486.         crc <<= 8;
  1487.     }
  1488.     
  1489.     
  1490.     errCode = GetResourceForkLength(&inSys67SFReply,&resForkLength);
  1491.     
  1492.     if (errCode != noErr)
  1493.         goto BINHEXERR;
  1494.     
  1495.     errCode = OpenResourceFork(&inSys67SFReply,&gReadFRefNum);
  1496.     
  1497.     if (errCode != noErr)
  1498.         goto BINHEXERR;
  1499.     
  1500.     gCRC = 0;
  1501.     gReadBufferBytesLeft = 0L;
  1502.     gHexBytesLeftToRead = resForkLength;
  1503.     
  1504.     for (i=0;i<resForkLength;i++)
  1505.     {
  1506.         if ((errCode = GetNextReadByte()) != noErr)
  1507.             goto BINHEXERR;
  1508.         
  1509.         gCurrentWriteByte = gCurrentReadByte;
  1510.         
  1511.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1512.             goto BINHEXERR;
  1513.     }
  1514.     
  1515.     
  1516.     if ((errCode = FSClose(gReadFRefNum)) != noErr)
  1517.     {
  1518.         gReadFRefNum = 0;
  1519.         sprintf(errorMessage,"ConvertFromBinhex: FSClose() error %d",errCode);
  1520.         goto BINHEXERR;
  1521.     }
  1522.     
  1523.     gReadFRefNum = 0;
  1524.     
  1525.     
  1526.     CalcCRC(0);
  1527.     CalcCRC(0);
  1528.     
  1529.     crc = gCRC;
  1530.     
  1531.     for (i=0;i<2;i++)
  1532.     {
  1533.         gCurrentWriteByte = (crc >> 8) & 0xFF;
  1534.         
  1535.         if ((errCode = PutByteToBinhexBuffer()) != noErr)
  1536.             goto BINHEXERR;
  1537.         
  1538.         crc <<= 8;
  1539.     }
  1540.     
  1541.     
  1542.     errCode = FlushBinhexBuffer();
  1543.     
  1544.     if (errCode != noErr)
  1545.         goto BINHEXERR;
  1546.     
  1547.     
  1548.     gWriteBufferIndex = 0;
  1549.     
  1550.     gWriteBuffer[gWriteBufferIndex++] = ':';
  1551.     gWriteBuffer[gWriteBufferIndex++] = '\r';
  1552.     
  1553.     
  1554.     errCode = WriteBinhexBuffer();
  1555.     
  1556.     if (errCode != noErr)
  1557.         goto BINHEXERR;
  1558.     
  1559.     if (errCode == noErr)
  1560.         goto NOBINHEXERR;
  1561.     
  1562.     
  1563.     
  1564.     
  1565. BINHEXERR:
  1566.     if (gBinhexHandle)
  1567.     {
  1568.         DisposHandle(gBinhexHandle);
  1569.     }
  1570.     
  1571.     gBinhexHandle = 0L;
  1572.     
  1573.     
  1574. NOBINHEXERR:
  1575.     if (gWriteFRefNum)
  1576.     {
  1577.         if (errCode == noErr)
  1578.         {
  1579.             errCode = FSClose(gWriteFRefNum);
  1580.             
  1581.             if (errCode != noErr)
  1582.             {
  1583.                 ExtractSFFileName(&outSys67SFReply,fileName);
  1584.                 
  1585.                 sprintf(errorMessage,"ConvertFromBinhex: FSClose('%s') error %d",fileName,errCode);
  1586.             }
  1587.         }
  1588.         
  1589.         else
  1590.             FSClose(gWriteFRefNum);
  1591.         
  1592.         gWriteFRefNum = 0;
  1593.     }
  1594.     
  1595.     if (gReadFRefNum)
  1596.     {
  1597.         if (errCode == noErr)
  1598.         {
  1599.             errCode = FSClose(gReadFRefNum);
  1600.             
  1601.             if (errCode != noErr)
  1602.             {
  1603.                 ExtractSFFileName(&inSys67SFReply,fileName);
  1604.                 
  1605.                 sprintf(errorMessage,"ConvertFromBinhex: FSClose('%s') error %d",fileName,errCode);
  1606.             }
  1607.         }
  1608.         
  1609.         else
  1610.             FSClose(gReadFRefNum);
  1611.             
  1612.         gReadFRefNum = 0;
  1613.     }
  1614.     
  1615.     if (!saveToDisk && theBinhexHandle)
  1616.     {
  1617.         SetHandleSize(gBinhexHandle,gBinhexIndex);
  1618.         
  1619.         *theBinhexHandle = gBinhexHandle;
  1620.     }
  1621.     
  1622.     if (errCode == USERCANCEL)
  1623.         errCode = noErr;
  1624.     
  1625.     return(errCode);
  1626. }